<template>
    <!-- tabs - 渲染 -->
    <el-tabs class="tabs-render" v-model="activeName" tab-position="left" @tab-click="handleClick">
        <el-tab-pane v-for="(item, index) in reportData" :key="index" :label="item.dictLabel" :name="item.dictValue_value"
            v-loading="loading"
            element-loading-text="数据加载中...">
            <span v-show="isReport" class="error-info">报表未发布，无法查看</span>
            <report-render :ref="`reportRender_${item.dictValue_value}`" @rederOver='rederOver'></report-render>
        </el-tab-pane>
        <!-- 选择 打印/导出数据 -->
        <yi-dialog class="print-select"
            title="选择打印或导出的报表内容"
            :visible.sync="dialogVisible"
            isHandle
            @confirm="confirm"
            confirmText="预览数据"
            width="300px">
            <yi-table ref="table" :data="reportData" @getData="getData" selection :index="false" @selection-change="handleSelectionChange">
                <el-table-column label="报表名称">
                    <template v-slot="{ row }">{{ row.dictLabel }}</template>
                </el-table-column>
            </yi-table>
        </yi-dialog>
        <!-- 预览 -->
        <yi-dialog class="render-dialog"
            title="打印/导出 预览效果"
            width="1000px"
            top="10vh"
            fullscreen
            isHandle
            :isConfirm="false"
            :visible.sync="print_dialogVisible"
        >
            <div :class="['print-box', { 'pdf': isPdf }]">
                <div class="reportRender-print" v-for="item in renderId" :key="item">
                    <report-render :ref="`reportRender_print_${item}`"></report-render>
                </div>
            </div>
            <span slot="more" class="render-function">
                <el-progress v-if="isPdf" :stroke-width="12" :percentage="exportPercentage"></el-progress>
                <el-button :icon="print_loading ? 'el-icon-loading': 'el-icon-printer'" :disabled="print_loading" size="small" type="primary" @click.stop="printer()">打印</el-button>
                <el-button :icon="export_loading ? 'el-icon-loading': 'el-icon-download'" :disabled="export_loading" size="small" type="primary" @click.stop="exportPDF()">导出</el-button>
            </span>
        </yi-dialog>
        <!-- 悬浮框 附件 -->
        <div class="suspended-dialog enclosureDialog" v-if="file.enclosure.length > 0">
            <div class="suspended-title">附件（可拖拽，移动位置）</div>
            <div class="suspended-content">
                <el-select v-model="file.fileId" size="mini" placeholder='查看附件' @change="handleEnclosure">
                    <el-option v-for="item in file.enclosure" :key="item.value" :label="item.lable" :value="item.value"></el-option>
                </el-select>
                <yi-table ref="suspendedTable" :data="file.fileInfos" stripe @getData="fileInfos_getData" :index="false" :show-header="false" height="80">
                    <el-table-column>
                        <template slot-scope="{ row }">
                            <span class="columnClick" @click.stop="handleFile(row)">{{ row.fileName }}</span>
                        </template>
                    </el-table-column>
                </yi-table>
            </div>
        </div>
        <!-- 悬浮框 - 锚点（仅针对计量支付报表工程量确认单） -->
        <div class="suspended-dialog anchor-point" v-if="file.enclosure.length > 0 && pointShow">
            <div class="suspended-title">目录（可拖拽，移动位置）</div>
            <div class="suspended-content">
                <li v-for="item in file.enclosure" :key="item.value">
                    <span @click.stop="goAnchor(item.lable)">{{ item.lable }}</span>
                </li>
            </div>
        </div>
        <!-- 计量报表查看-确认单功能 -->
        <yi-dialog class="render-dialog"
            title="查看确认单"
            width="835px"
            top="10vh"
            fullscreen
            isHandle
            :isConfirm="false"
            :visible.sync="confirmation_dialogVisible">
            <div class="confirmation-box">
                <report-render ref="reportRender_confirmation"></report-render>
            </div>
        </yi-dialog>
        <!-- 结算单报表 -->
        <yi-dialog title="结算单报表"
            :visible.sync="settlement_dialogVisible"
            width="1000px"
            fullscreen
            isHandle
            :isConfirm="false"
            top="10vh">
            <TabsRender ref="settlementTabsRender"></TabsRender>
            <div slot="more" class="more">
                <el-button type="primary" size="small" icon="el-icon-picture" @click="fileInfoData()">查看病害图片</el-button>
            </div>
        </yi-dialog>
        <!-- 病害图片预览 -->
        <yi-dialog title="病害图片"
            :visible.sync="picture_dialogVisible"
            width="800px"
            top="10vh">
            <el-descriptions :column="4" direction="vertical" size="small" border>
                <el-descriptions-item label="病害图片" span="4">
                    <div v-for="imageItem in preview.list1" :key="imageItem.id" class="avatar">
                        <el-image :src="imageItem.fileUrl" :preview-src-list="preview.src1"></el-image>
                    </div>
                </el-descriptions-item>
                <el-descriptions-item label="完工图片" span="4">
                    <div v-for="imageItem in preview.list2" :key="imageItem.id" class="avatar">
                        <el-image :src="imageItem.fileUrl" :preview-src-list="preview.src2"></el-image>
                    </div>
                </el-descriptions-item>
            </el-descriptions>
        </yi-dialog>
    </el-tabs>
</template>

<script>
import { warning, errorInfo } from "@/utils/errorInfo";
import EventBus from "../utils/eventBus";
import { ReportRender } from "../components/index";
import { selectCustomReportByIds, exportAllExcelStream } from "@/api/ReportDesign/ReportDesign.js";
import html2canvas from "html2canvas";
import jsPDF from 'jspdf';
// import { selectIntermediateMeteringMenu, selectIntermediateMeteringFile } from "@/api/ProjectProcessManagement/index";
// import { getBillingInfoByCode, getBillingInfoById } from "@/api/RoutineMaintenance/statementForm";
export default {
    name: "TabsRender",
    components: {
        ReportRender
    },
    props: {
        dictLabel: { // 报表参数需要dictLabel值时，需要传入参数key
            type: String,
            default: ""
        }
    },
    data() {
        return {
            params: {}, // 外部参数
            loading: false, // 报表弹框Loading
            activeName: "", // 报表tabsName
            reportData: [], // 报表数据
            isReport: false, // 报表是否发布
            dialogVisible: false, // 选择打印/导出的报表列表
            renderId: [], // 预览ID
            print_dialogVisible: false, // 打印/导出预览弹框
            export_loading: false, // 点击导出后的 Loading
            print_loading: false,
            isPdf: false, // 判断是否是 pdf 功能，增加特殊class
            exportPercentage: 0, // 导出进度条
            // 附件相关变量
            file: {
                fileId: '', // 附件ID
                fileInfos: [], // 附件数据
                enclosure: [] // 子目数据
            },
            imageSuffix: ["jpg", "png", "gif", "jpeg", 'pdf'],
            // 当前报表的绑定积木ID
            plugInID: null,
            // 当前报表整套是否增加水印
            isWatermark: null,
            pointShow: false, // 瞄点仅工程量确认单展示（特殊处理字段）
            // 计量报表查看确认单功能
            confirmation_dialogVisible: false,
            // 结算单
            settlement_dialogVisible: false,
            picture_dialogVisible: false,
            preview: {
                id: null,
                src1: [], // 图片预览1
                list1: [], // 图片列表1
                src2: [], // 图片预览2
                list2: [] // 图片列表2
            }
        }
    },
    methods: {
        rederOver(){
            this.$emit('rederOver')
        },
        init(dictName, params, isWatermark) { // 初始化加载
            this.params = params;
            this.isWatermark = isWatermark; // 水印
            this.loading = true;
            this.getDicts(dictName).then((res) => {
                let data = res?.data || [];
                data.forEach(item => {
                    item.dictValue_value = `${this.uuid(6, 16)}_${item.dictValue}`;
                })
                this.reportData = data;
                if (this.reportData && this.reportData.length > 0) {
                    // 处理 activeName
                    this.activeName = this.reportData[0].dictValue_value;
                    // 加载报表
                    if (this.reportData[0].dictValue != 0) this.loadReport(this.reportData[0].dictValue_value, this.reportData[0].dictLabel);
                    else warning('配置报表错误, 请重新设置');
                    // 附件
                    if (this.params.businessId) this.selectIntermediateMeteringMenu(this.params.businessId);
                } else {
                    this.loading = false;
                    this.isReport = true;
                }
            })
        },
        handleClick(val) {
            if (val.name) {
                this.loadReport(val.name, val.label);
                // 特殊处理 ------ 工程量确认单（展示瞄点视图区）
                if (val.label === '工程量确认单') {
                    this.pointShow = true;
                    // 锚点悬浮框
                    this.$nextTick(() => { this.draggableEvent('.anchor-point') });
                } else this.pointShow = false;
            }
        },
        loadReport(reportId, label) { // 加载报表
            this.loading = true;
            this.selectCustomReportByIds([this.parseUuid(reportId)]).then((report) => {
                let reportData = JSON.parse(report[0].content);
                this.plugInID = reportData.reportOption.plugInID || null; // 存储积木ID
                if (this.isWatermark == 0) reportData.elementItems.forEach(item => {
                    item.options.watermark = false;
                });
                if (this.dictLabel) this.$refs[`reportRender_${reportId}`][0].dataRender(reportData, { ...this.params, [this.dictLabel]: label});
                else this.$refs[`reportRender_${reportId}`][0].dataRender(reportData, this.params);
                this.loading = false;
            }).catch(() => {
                this.isReport = true;
                this.loading = false;
            })
        },
        selectCustomReportByIds(ids) { // 报表详情
            return new Promise((resolve, reject) => {
                selectCustomReportByIds(ids, { status: 2 }).then((res) => {
                    let data = res?.data || [];
                    if (data && data.length > 0) {
                        this.isReport = false;
                        resolve(data);
                    } else reject();
                })
            })
        },
        print(isWatermark) { // 打印调出选择弹框
            this.dialogVisible = true;
            this.isWatermark = isWatermark; // 水印
        },
        getData() {
            this.$refs.table.loading = false;
        },
        handleSelectionChange(val) { // 选择需要打印的内容
            this.renderId = val && val.map(item => item.dictValue);
        },
        confirm() {
            if (this.renderId.length > 0) {
                this.print_dialogVisible = true;
                this.selectCustomReportByIds(this.renderId).then((report) => {
                    report.forEach((item) => {
                        let reportData = JSON.parse(item.content);
                        if (this.isWatermark == 0) reportData.elementItems.forEach(item => {
                            item.options.watermark = false;
                        });
                        this.$refs[`reportRender_print_${item.id}`][0].dataRender(reportData, this.params);
                    })
                })
            } else warning('请选择需要预览打印/导出的报表');
        },
        printer() {
            this.print_loading = true;
            this.isPdf = true;
            let dom = document.querySelector('.print-box');
            let time = setTimeout(() => {
                this.generatePrint(dom).then(() => {
                    this.isPdf = false;
                    this.print_loading = false;
                });
                clearTimeout(time);
                time = null;
            }, 100);
        },
        generatePrint(dom) {
            return new Promise((resolve, reject) => {
                let reportItem = dom.querySelectorAll('.report-item');
                const pageNumber = Math.floor((100 / reportItem.length) * 10) / 10;
                let nextData = null;
                if (pageNumber > 0) nextData = reportItem.entries();
                let div = document.createElement('div');
                const printPage = (value) => { // 生成打印的图片
                    if (value.done) { // 结束
                        this.$print(div);
                        this.exportPercentage = 0;
                        resolve();
                    } else {
                        html2canvas(value.value[1], {
                            scale: 2,
                            backgroundColor: "#ffffff",
                            useCORS: true
                        }).then((canvas) => {
                            const imgData = canvas.toDataURL('image/jpeg', 1.0);
                            let img = document.createElement('img');
                            img.classList.add('printImg');
                            img.src = imgData;
                            div.appendChild(img);
                            // 进度条
                            if (this.exportPercentage >= 100) this.exportPercentage = 100;
                            else {
                                let value = this.exportPercentage + pageNumber;
                                value = this.$math.round(value, 1);
                                this.exportPercentage = value;
                            }
                            printPage(nextData.next());
                        })
                    }
                }
                if (nextData) printPage(nextData.next());
                else warning('打印异常，请稍后重试');
            })
        },
        exportPDF() {
            this.export_loading = true;
            this.isPdf = true;
            let dom = document.querySelector('.print-box');
            let time = setTimeout(() => {
                this.generatePDF(dom).then(() => {
                    this.isPdf = false;
                    this.export_loading = false;
                });
                clearTimeout(time);
                time = null;
            }, 100);
        },
        generatePDF(dom) {
            return new Promise((resolve, reject) => {
                let reportItem = dom.querySelectorAll('.report-item');
                const pageNumber = Math.floor((100 / reportItem.length) * 10) / 10;
                const pdf = new jsPDF('', 'pt', 'a4');
                let nextData = null;
                if (pageNumber > 0) nextData = reportItem.entries();
                const pdfPage = (value) => {
                    if (value.done) { // 结束
                        pdf.save(`导出.pdf`);
                        this.exportPercentage = 0;
                        resolve();
                    } else {
                        html2canvas(value.value[1], {
                            scale: 2,
                            backgroundColor: "#ffffff",
                            useCORS: true // 是否尝试使用CORS从服务器加载图像 (allowTaint 允许跨域 不允许同时true)
                        }).then((canvas) => {
                            const contentWidth = canvas.width;
                            const contentHeight = canvas.height;
                            const imgWidth = 595.28;
                            const imgHeight = (595.28 / contentWidth) * contentHeight;
                            const pageData = canvas.toDataURL('image/jpeg', 1.0);
                            pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
                            if (value.value[0] !== (reportItem.length - 1)) pdf.addPage();
                            // 导出进度条
                            if (this.exportPercentage >= 100) this.exportPercentage = 100;
                            else {
                                let value = this.exportPercentage + pageNumber;
                                value = this.$math.round(value, 1);
                                this.exportPercentage = value;
                            };
                            // end
                            pdfPage(nextData.next());
                        });
                    }
                }
                if (nextData) pdfPage(nextData.next());
                else warning('导出异常，请稍后重试');
            })
        },
        // 附件
        selectIntermediateMeteringMenu(meteringReportId) {
            selectIntermediateMeteringMenu({ meteringReportId }).then((res) => {
				this.file.enclosure = res?.data || [];
                if (this.file.enclosure.length > 0) this.handleMove();
			});
        },
        handleEnclosure(val) {
            selectIntermediateMeteringFile({ intermediateMeteringId: val }).then((res) => {
				this.file.fileInfos = res?.data || [];
			})
        },
        fileInfos_getData() {
            this.$refs.suspendedTable.loading = false;
        },
        handleFile(data) { // 下载附件
            let suffix = this.suffixSlice(data.fileName);
            let a = document.createElement('a');
			a.style.display = 'none';
			a.href = data.fileUrl;
			if (!this.imageSuffix.includes(suffix)) a.download = data.fileName;
            a.target = "_blank";
			document.body.appendChild(a);
			a.click();
			URL.revokeObjectURL(a.href);
			document.body.removeChild(a);
			a = null;
        },
        suffixSlice(fileName) { // 文件后缀截取
            let suffixIndex = fileName.lastIndexOf('.');
            let suffixName = fileName.slice(suffixIndex + 1, fileName.length);
            return suffixName;
        },
        // 给悬浮框增加可以自定义移动
        handleMove() {
            this.$nextTick(() => {
                // 附件悬浮框
                this.draggableEvent('.enclosureDialog');
            })
        },
        draggableEvent(dom) { // 拖动函数
            let draggableDom = document.querySelector(dom);
            let draggable = draggableDom.querySelector('.suspended-title');
            draggable.onmousedown = (mousedownE) => {
                let disX = mousedownE.clientX - draggableDom.offsetLeft;
                let disY = mousedownE.clientY - draggableDom.offsetTop;
                document.onmousemove = (mousemoveE) => {
                    let left = mousemoveE.clientX - disX;
                    let top = mousemoveE.clientY - disY;
                    draggableDom.style.left = left + 'px';
                    draggableDom.style.top = top + 'px';
                    // 可增加拖拽范围
                }
            }
            draggable.onmouseup = () => {
                document.onmousemove = null;
            }
        },
        // 锚点
        goAnchor(selector) {
            let anchorList = this.$refs[`reportRender_${this.activeName}`][0].$el.querySelectorAll('.anchor');
            if (anchorList && anchorList.length > 0) {
                anchorList.forEach(item => {
                    if (item.anchorId === selector) {
                        item.scrollIntoView({ behavior: "smooth" });
                        anchorList = null;
                    }
                })
            }
            // 附件同步处理
            this.file.fileId = this.file.enclosure.find(item => item.lable === selector)?.value;
            this.handleEnclosure(this.file.fileId);
        },
        excel() { // 导出excel
            if (this.plugInID) {
                exportAllExcelStream({
                    excelConfigId: this.plugInID,
                    queryParam: {
                        ...this.params,
                        pageNo: 1,
                        pageSize: 500,
                        currentPageNo: 1,
                        currentPageSize: 500
                    }
                }).then((res) => {
                    this.streamDownload(res.data, `${this.activeName}.xlsx`);
                })
            } else {
                warning('未绑定插件报表ID,无法导出Excel');
            }
        },
        // 流媒体下载
        streamDownload(stream, fileName){
            if (stream && stream.size > 100){
                if (window.navigator.msSaveOrOpenBlob){
                    navigator.msSaveOrOpenBlob(new Blob([stream]), `${fileName}`);
                } else {
                    let blob = new Blob([stream]);
                    let a = document.createElement('a');
                    a.href = window.URL.createObjectURL(blob);
                    a.download = `${fileName}`;
                    a.click();
                    a = null;
                }
            } else {
                errorInfo('下载失败,请重新尝试');
            }
        },
        // 8位uuid
        uuid(len, radix) {
            let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
            let uuid = [], i;
            radix = radix || chars.length;
            if (len) {
                for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
            } else {
                let r;
                uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
                uuid[14] = '4';
                for (i = 0; i < 36; i++) {
                    if (!uuid[i]) {
                        r = 0 | Math.random() * 16;
                        uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
                    }
                }
            }
            return uuid.join('');
        },
        parseUuid(value) { // 解析报表ID（uuid_id） 解析仅需要id
            let arr = value.split('_');
            return arr[1];
        },
        confirmationHandle() { // 确认单处理
            EventBus.$off('confirmation');
            EventBus.$on('confirmation', (data) => {
                if (data.suborder_name && data.currentAmount && Number(data.currentAmount) > 0) {
                    // 处理附件
                    this.file.fileId = this.file.enclosure.find(item => item.lable === data.suborder_no)?.value;
                    this.file.fileId && this.handleEnclosure(this.file.fileId);
                    // 处理报表
                    this.confirmation_dialogVisible = true;
                    this.selectCustomReportByIds(['1590602838461411330']).then((report) => {
                        let reportData = JSON.parse(report[0].content);
                        this.$refs.reportRender_confirmation.dataRender(reportData, {
                            businessId: data.id
                        });
                    })
                } else warning('此数据无确认单');
            })
        },
        settlementHandle() { // 结算单功能
            EventBus.$off('settlement');
            EventBus.$on('settlement', (data) => {
                getBillingInfoByCode({ code: data.billingCode }).then((res) => {
                    let data = res?.data || {};
                    this.preview.id = data.id;
                    this.settlement_dialogVisible = true;
                    this.$nextTick(() => {
                        this.$refs.settlementTabsRender.init('maintenance_report', {
                            businessId: data.id,
                            dispatchId: data.dispatchId,
                            acceptId: data.acceptId
                        });
                    })
                })
            })
        },
        fileInfoData() { // 结算单查看病害图片
            this.picture_dialogVisible = true;
            getBillingInfoById({ id: this.preview.id }).then((res) => {
                let data = res?.data || {};
                this.preview.src1.length = 0;
                this.preview.src2.length = 0;
                this.preview.list1.length = 0;
                this.preview.list2.length = 0;
                this.$nextTick(() => {
                    let fileInfoList = data.roadPlantdises.map(item => {
                        return item.fileInfoList;
                    });
                    let previewList = fileInfoList.flat();
                    this.preview.src1 = previewList.filter(item => item.type == 1).map(item => item.fileUrl);
                    this.preview.src2 = previewList.filter(item => item.type == 2).map(item => item.fileUrl);
                    this.preview.list1 = previewList.filter(item => item.type == 1);
                    this.preview.list2 = previewList.filter(item => item.type == 2);
                })
            })
        }
    },
    mounted() {
        this.confirmationHandle(); // 确认单查看功能
        this.settlementHandle(); // 查看结算单功能
    }
}
</script>

<style>
    @import url('./TabsRender.css');
</style>